CrackMe v. 1.00
by aLoNg3x


Tutorial by Lucifer48 [Immortal Descendants]
(1 august 1999)


The crackme is written in delphi... with this beautiful icon...
I fill my name and my serial (i put a bpx hmemcpy), it's very classical:
XXXX:00442C9C  CALL 004232C0		;we exit from here
XXXX:00442CA1  MOV  EAX,[EBP-08]
XXXX:00442CA4  LEA  EDX,[EBP-04]
...
XXXX:00442D07  MOV  EAX,[EBP-10]	;name
XXXX:00442D0A  POP  EDX			;serial
XXXX:00442D0B  CALL 00442A3C		;check the serial
XXXX:00442D10  TEST AL,AL
XXXX:00442D12  JZ   00442D23            ;jump = bad serial
This a small source in Borland C++ Builder (v4.0) to show what's happen in the call 00442A3C:
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyUp(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
int i, result=0;
AnsiString name;
name=Edit1->Text;               /* Edit1: edit box for the name */

if ((name!="")&&(name.Length()>5)&&(name.Length()<11))
  {
  for(i=1; i<name.Length(); i++)
    result += name[i+1]*name[i]*i;
  result = result + name.Length() - 666;
  Edit2->Text=result;
  }
else
  Edit2->Text="";               /* Edit2: edit box for the serial */
}
//---------------------------------------------------------------------------
I get my own registration:
Name/ Lucifer48
Serial/ 290812

With that, the "OK" button is enabled, i click on it and nothing ! The "OK" button is disabled again. I try to see, what's happen when i click on ok and nothing interesting... The check is elsewhere...

In fact, the true check is done when you click on the "Cancella" button; it is practically the same code as above:
...
XXXX:00442EE3  MOV  EAX,[EBP-04]		;name
XXXX:00442EE6  POP  EDX				;edx:  value of the serial in hexa
XXXX:00442EE7  CALL 00442AF4			;check
XXXX:00442EEC  TEST AL,AL
XXXX:00442EEE  JZ   00442F0C			;jump = bad serial
In the call 00442AF4:
XXXX:00442B3A  CALL 00442A20			;EAX! i mean: fact(eax)
XXXX:00442B3F  MOV  ESI,EAX			;save the result
...
XXXX:00442B4F  MOV  EDX,00000001
XXXX:00442B54  MOV  ECX,[EBP-04]		;adress of name
XXXX:00442B57  MOVZX ECX,BYTE PTR [EDX+ECX-01]  ;read one by one the chars of the name
XXXX:00442B5C  IMUL ECX,ESI
XXXX:00442B5F  ADD  EBX,ECX
XXXX:00442B61  INC  EDX
XXXX:00442B62  DEC  EAX
XXXX:00442B63  JNZ  00442B54			;loop (length of name)
XXXX:00442B65  SUB  EBX,[EBP-08]		;the serial (in hexa)
XXXX:00442B68  CMP  EBX,00007A69
XXXX:00442B6E  JNZ  00442B74			;must be equal...
This is a small part of the keygen:
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyUp(TObject *Sender, WORD &Key,
      TShiftState Shift)
{
int i, f, result=0;
AnsiString name;
name=Edit1->Text;               /* Edit1: edit box for the name */

if ((name!="")&&(name.Length()>5)&&(name.Length()<11))
  {
  f=fact((name[5]%7)+2);	/* fact(n) = 1*2*...*(n-1)*n */
  for(i=1; i<=name.Length(); i++)
    result = result + name[i]*f;
  result -= 0x7a69;
  Edit2->Text=result;
  }
else
  Edit2->Text="";               /* Edit2: edit box for the serial */
}
//---------------------------------------------------------------------------
I press on the "Cancella" button; it is erased. We passed a step ! Still one button.

I get my own registration:
Name/ Lucifer48
Serial/ 560503

Note: There is no problem to enter negative numbers. (example: Name/ L48 [ID] Serial/ -30255 )

Remark: I'd like to say few words about the way delphi has compiled the factorial function (in the call 00442A20):
XXXX:00442A20  PUSH EBX			;13 lines of code only !!
XXXX:00442A21  MOV  EBX,EAX		;and nothing superfluous !!
XXXX:00442A23  TEST EBX,EBX
XXXX:00442A25  JNZ  00442A2E
XXXX:00442A27  MOV  EAX,000000001	;
XXXX:00442A2C  POP  EBX			;end of recursion
XXXX:00442A2D  RET			:
XXXX:00442A2E  MOV  EAX,EBX
XXXX:00442A30  DEC  EAX
XXXX:00442A31  CALL 00442A20
XXXX:00442A36  IMUL EBX			;
XXXX:00442A38  POP  EBX			;(result of the multiplication EDX:EAX, with EDX dword..
XXXX:00442A39  RET			; ..of high weigth)
We find this algo in high level languages: Let's continue the crackme, we have to kill the "OK" button (with the same way of above):
XXXX:00442DBD  MOV  EAX,[EBP-04]		;name
XXXX:00442DC0  POP  EDX				;serial (in hexa)
XXXX:00442DC1  CALL 004232C0			;check the serial
XXXX:00442DC6  TEST AL,AL
XXXX:00442DC8  JZ   00442DD7			;jump = bad serial
In the call 004232C0:
XXXX:00442C09  MOVZX EAX,BYTE PTR [ESI+EAX-01]
XXXX:00442C0E  IMUL  EAX			;EAX^2
XXXX:00442C10  MOVSX EAX,AX			;if AX>7FFF then EAX=(EAX or $FFFF0000)
XXXX:00442C13  IMUL  ESI
XXXX:00442C15  MOV   ECX,00000019		;1A would be better for getting a "Z" char...
XXXX:00442C1A  CDQ
XXXX:00442C1B  IDIV  ECX
XXXX:00442C1D  ADD   EDX,41
XXXX:00442C20  POP   EAX
XXXX:00442C21  MOV   [EAX],DL			;adress of the serial
XXXX:00442C23  DEC   ESI			;we start by the last char
XXXX:00442C24  TEST  ESI,ESI
XXXX:00442C26  JNZ   00442BF9			;loop (length of serial)
XXXX:00442C28  MOV   EAX,[EBP-0C]		;serial "encoded"
XXXX:00442C2B  MOV   EDX,[EBP-04]		;name
XXXX:00442C2E  CALL  00403B44			;comparison of the two strings
XXXX:00442C33  JNZ   00442C4C                   ;jump = bad serial
If you look at the loop, you see that the name must only have capitals letter (from 41h to 59h, without the Z char...) And of course, the serial and the name have the same length.

Let's find (or rather let's try to find...) a serial for my name:
L  U  C  I  F  E  R
4C 55 43 49 46 45 52
I recall that; we only can enter numbers in the serial. So:
(X7^2 * 7) mod 19 + 41 = 52   <=>   (X7^2 * 7) mod 19 = 11
(X6^2 * 6) mod 19 + 41 = 45   <=>   (X6^2 * 6) mod 19 = 04
(X5^2 * 5) mod 19 + 41 = 46   <=>   (X5^2 * 5) mod 19 = 05
(X4^2 * 4) mod 19 + 41 = 49   <=>   (X4^2 * 4) mod 19 = 08
(X3^2 * 3) mod 19 + 41 = 43   <=>   (X3^2 * 3) mod 19 = 02
(X2^2 * 2) mod 19 + 41 = 55   <=>   (X2^2 * 2) mod 19 = 14
(X1^2 * 1) mod 19 + 41 = 4C   <=>   (X1^2 * 1) mod 19 = 0B
I've done a small prog on my calculator which try the 10 (unique) possibilities (from 30h to 39h):
For X7: i get: { 3h, 7h, 0h, 7h, 3h, Dh, Ch, 0h, 2h, 12h }
For X6: i get: { 18h, 6h, 0h, 6h, 18h, 4h, 15h, 0h, 10h, 13h }
For X5: i get: { 14h, 5h, 0h, 5h, 14h, 14h, 5h, 0h, 5h, 14h }
For X4: i get: { 10h, 4h, 0h, 4h, 10h, Bh, Eh, 0h, 13h, 15h }
For X3: i get: { Ch, 3h, 0h, 3h, Ch, 2h, 17h, 0h, 8h, 16h }
For X2: i get: { 8h, 2h, 0h, 2h, 8h, 12h, 7h, 0h, 16h, 17h }
For X1: i get: { 4h, 1h, 0h, 1h, 4h, 9h, 10h, 0h, Bh, 18h }
We see that X7, X4 and X2 are impossible to solve ! A big error from the author...

Acceptable chars (in the right order):
For X7: "D","H","A","H","D","N","M","A","C","S"
For X6: "Y","G","A","G","Y","E","V","A","Q","T"
For X5: "U","F","A","F","U","U","F","A","F","U"
For X4: "Q","E","A","E","Q","L","O","A","T","V"
For X3: "M","D","A","D","M","C","X","A","I","W"
For X2: "I","C","A","C","I","S","H","A","W","X"
For X1: "E","B","A","B","E","J","Q","A","L","Y"
With this, i can't build my name... I can do

Name/ LICQFED
Serial/ 8050150 (or 8050350 or...)

Or more simply:
Name/ AAAAAA
Serial/ 222222

Remark: To be complete; we can put a "-" char as first char of the serial. So 2Dh become "A".

The "OK" button is erased...

Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, LaZaRuS, Duelist, people on #cracking4newbies, ...



(c) Lucifer48. All rights reversed